package exam;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Deque;
import java.util.LinkedList;
import java.util.List;

/**
 * Tests the answer to the first queue question.
 * The text of the question is as follows:
 * "Write an add method for a priority queue that stores Student objects who are trying to 
 *  register.  Students with more credits should have a higher priority rating.  Note that ICS 
 *  majors should generally be moved to the front of the priority queue, but should remain in 
 *  sorted order amongst other ICS majors.  If a student is an ICS major, then the getMajor method
 *  for that Student should return "ICS"."
 * 
 * @author Branden Ogata
 *
 */

public class TestQueueA00 extends Tester
{
  public static void main(String[] args)
  {
    final double POINTS = getPoints(args);
    
    Deque<Student> queue = new LinkedList<Student>();
    Deque<Student> solution = new LinkedList<Student>();
    Student ics0 = new Student("Paul E. Gone", "ICS", 128);
    Student ics1 = new Student("Al Arm", "ICS", 64);
    Student ics2 = new Student("Al B. Back", "ICS", 8); // in 2^x and Fibonacci sequence
    Student non0 = new Student("Ira Fuse", "Chemistry", 4); // C4
    Student non1 = new Student("Dewey Havtoo", "LIS", 23); // current version of Dewey Decimal Sys
    Student non2 = new Student("Sandy Beech", "Oceanography", 18); // appx. molar mass of water
    Student non3 = new Student("Toby R. Notabee", "English", 37); // number of Shakespeare plays
    Student non4 = new Student("Luke Out", "Opthamology", 2); // two eyes
    Student non5 = new Student("Robin Banks", "Political Science", 535); // 535 in Congress
    Student non6 = new Student("Hugh Blewitt", "Political Science", 15); // 15 Cabinet members
    Student non7 = new Student("Millie Meter", "Chemistry", 1000); // 1000 mm in 1 m
    Student non8 = new Student("Marcus Absent", "Math", 227); // pi in ASCII decimal values
    
    // Empty, adding a non-ICS major
    QueueA00.add(queue, non0);
    solution.offer(non0);
    System.out.println(test(Category.EQUALS, "add([], \"" + non0.getName() + "\")", 
                            solution, queue, percentageToPoints(SIXTEENTH, POINTS)));
    queue.clear();
    solution.clear();
    
    // Empty, adding an ICS major
    QueueA00.add(queue, ics0);
    solution.offer(ics0);
    System.out.println(test(Category.EQUALS, "add([], \"" + ics0.getName() + "\")", 
                            solution, queue, percentageToPoints(SIXTEENTH, POINTS)));
    queue.clear();
    solution.clear();
    
    // One ICS major, adding a higher-priority ICS major
    queue.offer(ics1);
    QueueA00.add(queue, ics0);
    solution.offer(ics0);
    solution.offer(ics1);
    System.out.println(test(Category.EQUALS, "add([\"" + ics1.getName() + "\"], " + 
                                             "\"" + ics0.getName() + "\")", 
                            solution, queue, percentageToPoints(SIXTEENTH, POINTS)));
    queue.clear();
    solution.clear();
    
    // One ICS major, adding a lower-priority ICS major
    queue.offer(ics1);
    QueueA00.add(queue, ics2);
    solution.offer(ics1);
    solution.offer(ics2);
    System.out.println(test(Category.EQUALS, "add([\"" + ics1.getName() + "\"], " + 
                                             "\"" + ics2.getName() + "\")", 
                            solution, queue, percentageToPoints(SIXTEENTH, POINTS)));
    queue.clear();
    solution.clear();
    
    // One ICS major, adding a non-ICS major
    queue.offer(ics2);
    QueueA00.add(queue, non1);
    solution.offer(ics2);
    solution.offer(non1);
    System.out.println(test(Category.EQUALS, "add([\"" + ics2.getName() + "\"], " + 
                                             "\"" + non1.getName() + "\")", 
                            solution, queue, percentageToPoints(SIXTEENTH, POINTS)));
    queue.clear();
    solution.clear();
     
    // One non-ICS major, adding an ICS major
    queue.offer(non2);
    QueueA00.add(queue, ics0);
    solution.offer(ics0);
    solution.offer(non2);
    System.out.println(test(Category.EQUALS, "add([\"" + non2.getName() + "\"], " + 
                                             "\"" + ics0.getName() + "\")", 
                            solution, queue, percentageToPoints(SIXTEENTH, POINTS)));
    queue.clear();
    solution.clear();
 
    // One non-ICS major, adding a higher-priority non-ICS major
    queue.offer(non3);
    QueueA00.add(queue, non8);
    solution.offer(non8);
    solution.offer(non3);
    System.out.println(test(Category.EQUALS, "add([\"" + non3.getName() + "\"], " + 
                                             "\"" + non8.getName() + "\")", 
                            solution, queue, percentageToPoints(SIXTEENTH, POINTS)));
    queue.clear();
    solution.clear();
 
    // One non-ICS major, adding a lower-priority non-ICS major
    queue.offer(non5);
    QueueA00.add(queue, non4);
    solution.offer(non5);
    solution.offer(non4);
    System.out.println(test(Category.EQUALS, "add([\"" + non5.getName() + "\"], " + 
                                             "\"" + non4.getName() + "\")", 
                            solution, queue, percentageToPoints(SIXTEENTH, POINTS)));
    queue.clear();
    solution.clear();
 
    // One ICS major and one non-ICS major, adding a higher-priority ICS major
    queue.offer(ics1);
    queue.offer(non6);
    QueueA00.add(queue, ics0);
    solution.offer(ics0);
    solution.offer(ics1);
    solution.offer(non6);
    System.out.println(test(Category.EQUALS, "add([\"" + ics1.getName() + "\", " + 
                                             "\"" + non6.getName() + "\"], " + 
                                             "\"" + ics0.getName() + "\")", 
                            solution, queue, percentageToPoints(SIXTEENTH, POINTS)));
    queue.clear();
    solution.clear();
    
    // One ICS major and one non-ICS major, adding a lower-priority ICS major
    queue.offer(ics1);
    queue.offer(non7);
    QueueA00.add(queue, ics2);
    solution.offer(ics1);
    solution.offer(ics2);
    solution.offer(non7);
    System.out.println(test(Category.EQUALS, "add([\"" + ics1.getName() + "\", " + 
                                             "\"" + ics2.getName() + "\"], " + 
                                             "\"" + non7.getName() + "\")", 
                            solution, queue, percentageToPoints(SIXTEENTH, POINTS)));
    queue.clear();
    solution.clear();
    
    // One ICS major and one non-ICS major, adding a higher-priority non-ICS major
    queue.offer(ics0);
    queue.offer(non0);
    QueueA00.add(queue, non1);
    solution.offer(ics0);
    solution.offer(non1);
    solution.offer(non0);
    System.out.println(test(Category.EQUALS, "add([\"" + ics0.getName() + "\", " + 
                                             "\"" + non0.getName() + "\"], " + 
                                             "\"" + non1.getName() + "\")", 
                            solution, queue, percentageToPoints(SIXTEENTH, POINTS)));
    queue.clear();
    solution.clear();
    
    // One ICS major and one non-ICS major, adding a lower-priority non-ICS major
    queue.offer(ics2);
    queue.offer(non3);
    QueueA00.add(queue, non2);
    solution.offer(ics2);
    solution.offer(non3);
    solution.offer(non2);
    System.out.println(test(Category.EQUALS, "add([\"" + ics2.getName() + "\", " + 
                                             "\"" + non3.getName() + "\"], " + 
                                             "\"" + non2.getName() + "\")", 
                            solution, queue, percentageToPoints(SIXTEENTH, POINTS)));
    queue.clear();
    solution.clear();
    
    // Adding all in random order should still produce a sorted queue
    List<Student> students = new ArrayList<Student>(Arrays.asList(ics0, ics1, ics2, non0, 
                                                                  non1, non2, non3, non4, 
                                                                  non5, non6, non7, non8));
    Collections.shuffle(students);
    
    for (Student s : students)
    {
      QueueA00.add(queue, s);
    }
    
    solution.addAll(Arrays.asList(ics0, ics1, ics2, non7, non5, non8, 
                                  non3, non1, non2, non6, non0, non4));
    
    System.out.println(test(Category.EQUALS, "Offered all students", solution, queue, 
                            percentageToPoints(FOURTH, POINTS)));
    
    // Extra credit for handling items of the same value
    
    System.out.format("[%.2f/%.2f]%n", getTotalPoints(), POINTS);
  }
}
